package cn.maihe.elg.operation.institution;

import cn.maihe.elg.operation.common.TradeContext;
import cn.maihe.elg.operation.model.dto.BaseReq;
import cn.maihe.elg.operation.model.dto.BaseResp;
import cn.maihe.elg.operation.model.dto.InnerBaseResp;
import cn.maihe.elg.operation.model.enums.InnerRespCode;
import cn.maihe.elg.operation.utils.ElgLogger;
import cn.maihe.elg.operation.utils.ValidateUtil;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import lombok.extern.slf4j.Slf4j;

import java.util.Map;

/**
 * @Description
 * @Author WJH
 * @Date 2021/04/25
 */
@Slf4j
public abstract class BaseInstitutionOpenService<REQ extends BaseReq, RESP extends BaseResp> {

    protected final ObjectMapper objectMapper ;

    public BaseInstitutionOpenService() {
        objectMapper = new ObjectMapper();
        objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
        objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
    }

    /**
     * 业务处理
     *
     * @param req     请求参数|实际业务&参与签名验签数据
     * @param attrMap 临时传值属性
     * @return
     */
    public InnerBaseResp<RESP> doService(final REQ req, final Map<String, Object> attrMap) {
        TradeContext<REQ, RESP> context = new TradeContext<>(req, attrMap);
        ElgLogger.debug(log, l -> l.debug("traceId[{}] => 请求报文:{},附属属性:{}", context.getTraceId(), toJsonString(req), toJsonString(attrMap)));

        try {
            //参数校验
            verifyReq(context);
        } catch (Exception e) {
            ElgLogger.error(log, l -> l.error("traceId[{}] => 响应报文", context.getTraceId(), "参数校验失败:" + e.getMessage()));
            return InnerBaseResp.of(InnerRespCode.FAILURE_PARAM, e.getMessage(), null);
        }

        // fixme 内部调用暂无签名验签

        RESP resp;
        try {
            resp = processBusiness(context);
            ElgLogger.debug(log, l -> l.debug("traceId[{}] => 响应报文", context.getTraceId(), toJsonString(resp)));
            return InnerBaseResp.success(resp);
        } catch (Exception e) {
            ElgLogger.error(log, l -> l.error("traceId[{}] => 响应报文", context.getTraceId(), e.getMessage(),e));
            return InnerBaseResp.exception(e.getMessage());
        }

    }

    /**
     * 业务处理
     *
     * @param context
     * @return
     */
    protected abstract RESP processBusiness(TradeContext<REQ, RESP> context);

    private void verifyReq(TradeContext<REQ, RESP> context) {
        try {
            REQ req = context.getReq();
            ValidateUtil.validate(req);
        } catch (Exception e) {
            throw new InstitutionException("参数校验失败:" + e.getMessage(), e);
        }
    }

    protected final String toJsonString(Object obj) {
        try {
            return objectMapper.writeValueAsString(obj);
        } catch (JsonProcessingException e) {
            throw new InstitutionException("转换json字符串异常", e);
        }
    }


}
